package com.yeskery.nut.extend.mcp.server;

import com.yeskery.nut.application.NutApplication;
import com.yeskery.nut.core.CommandLineRunner;
import com.yeskery.nut.core.RequestHandler;
import com.yeskery.nut.core.ThreadPool;

import java.io.PrintStream;
import java.util.concurrent.BlockingQueue;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Mcp Stdio 服务处理监听器
 * @author sprout
 * 2025-05-21 11:06
 */
public class McpStdioServerHandleListener implements CommandLineRunner {

    /** 日志对象 */
    private final Logger logger = Logger.getLogger(McpStdioServerHandleListener.class.getName());

    /** nut应用对象 */
    private final NutApplication nutApplication;

    /** 请求处理器 */
    private final RequestHandler requestHandler;

    /** 阻塞队列 */
    private final BlockingQueue<StdioRequest> blockingQueue;

    /** 线程池对象 */
    private final ThreadPool threadPool;

    /** 响应线程 */
    private Thread responseThread;

    /** 响应处理器 */
    private StdioResponseHandler stdioResponseHandler;


    /**
     * 构造Mcp Stdio 服务处理监听器
     * @param nutApplication nut应用对象
     * @param requestHandler 请求处理器
     * @param blockingQueue 阻塞队列
     */
    public McpStdioServerHandleListener(NutApplication nutApplication, RequestHandler requestHandler, BlockingQueue<StdioRequest> blockingQueue) {
        this.nutApplication = nutApplication;
        this.requestHandler = requestHandler;
        this.blockingQueue = blockingQueue;
        this.threadPool = nutApplication.getDefaultThreadPool();
    }

    @Override
    public void run(String[] strings) throws Exception {
        stdioResponseHandler = new StdioResponseHandler();
        responseThread = new Thread(stdioResponseHandler);
        responseThread.start();
    }

    /**
     * 关闭方法
     */
    public void close() {
        if (stdioResponseHandler != null) {
            stdioResponseHandler.close();
        }
        if (responseThread != null) {
            responseThread.interrupt();
        }
    }

    /**
     * 基于Stdio响应处理器
     * @author sprout
     * 2025-05-22 09:48
     */
    private class StdioResponseHandler implements Runnable {

        /** 输出流 */
        private final PrintStream printStream = new PrintStream(System.out, true);

        @Override
        public void run() {
            while (true) {
                try {
                    StdioRequest stdioRequest = blockingQueue.take();
                    threadPool.getThreadPool().execute(() -> {
                        try {
                            StdioResponse response = new StdioResponse(nutApplication, printStream);
                            requestHandler.handle(stdioRequest, response, null);
                            printStream.print('\n');
                            printStream.flush();
                        } catch (Exception e) {
                            logger.log(Level.SEVERE, "Mcp Stdio Response Failure.", e);
                        }
                    });
                } catch (InterruptedException e) {
                    logger.log(Level.SEVERE, "Mcp Stdio Response Interrupted.", e);
                    break;
                }
            }
        }

        /**
         * 关闭方法
         */
        public void close() {
            printStream.close();
        }
    }
}
